package cn.edu.nju.ws.sview.views;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;

import cn.edu.nju.ws.sview.cache.URIIDCache;
import cn.edu.nju.ws.sview.cache.ViewCache;
import cn.edu.nju.ws.sview.database.DBConnectionFactory;
import cn.edu.nju.ws.sview.database.DBOperations;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.views.CustomDataMember.Base;
import cn.edu.nju.ws.sview.views.data.Management;



public class View {
    public final static long VIEW_CACHE_UPDATE_PERIOD;	
	private String name = null;
	private int id ;
	private String group = null;
	// for innerclass, classURI's uri equals innerclass id
	private URIResource classURI = null;
	private String language = null;
	private int useTimes = -1;
	private boolean isInner;
	private String status = null;//"favor","pop"/null,"trash"
	
	
	public static final String STATUS_FAVOR="favorite";
	public static final String STATUS_POP="available";
	public static final String STATUS_TRASH="trashed";
	
    static{
   	 Properties properties = new Properties();
   	 try {
			properties.load(View.class.getClassLoader().getResourceAsStream("conf.properties")) ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int days = Integer.parseInt(properties.getProperty("view_cache_update_period"));
		long t = days*24*60*60*1000L;
		VIEW_CACHE_UPDATE_PERIOD = t;
		properties.clear();
    }
	
	public View(String name, String group, boolean isInner,String classURIString,String lang) {
		this.name = name;
		this.group = group;
		this.isInner = isInner;
		this.classURI = ResourceFactory.getInstance().
							createURIResource(classURIString);
		this.language = lang;
	}
	public void setStatus(String status){
		this.status = status;
	}
	public String getStatus(){
		return this.status;
	}
	/**
	 * make inner class uri string  which equals innerclass id
	 * @param innerClassID
	 * @return
	 */
	private static String makeInnerClassURIStr(int innerClassID){
		String str = ""+innerClassID;
		return str;
	}
	
	public static String genClassURIStr(boolean isInner,int classID){
		String result = null;
		if(!isInner){
			result = URIResource.getURIResourceById(classID).getURI();
		}else{
			result = makeInnerClassURIStr(classID) ;
		}
		return result;
	}
	
	public static String getClassURIStrByViewID(int viewID){
		boolean isInner = View.isInner(viewID);
		int classID = View.getClassIDByViewID(viewID);
		return View.genClassURIStr(isInner, classID);
	}
	
	private  int computeClassID(){
		int classID = -1;
		if(!this.isInner){
			try {
				classID = URIIDCache.getInstance().getURIID(this.classURI.getURI(), true);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			classID = Integer.parseInt(this.classURI.getURI());
		}
		return classID;
	}
	
	/**
	 * 判断以viewId标识的view是否还存在
	 * @param viewId
	 * @return
	 */
	static public boolean isThere(int viewId){
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select null from view where id=?") ;
			stmt.setInt(1, viewId) ;
			ResultSet rs = stmt.executeQuery();
			if ( rs.next() ) {
				result = true;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	static public View getViewByViewId(int viewId, String status) {
		View view = null;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select name,group_id,isInner,class_id,lang from view where id=?") ;
			stmt.setInt(1, viewId) ;
			ResultSet rs = stmt.executeQuery();
			if ( rs.next() ) {
				String lang = rs.getString("lang") ;
				String name = rs.getString("name");
				boolean isInner  = rs.getBoolean("isInner") ;
				String group = User.getUserNameById(rs.getInt("group_id"));
				int classID = rs.getInt("class_id");
				URIResource classURI = null;
				if(!isInner){
					classURI = URIResource.getURIResourceById(classID);
				}else{
					String classURIStr = makeInnerClassURIStr(classID) ;
					classURI = ResourceFactory.getInstance().createURIResource(classURIStr);
				}
				view = new View(name, group, isInner,classURI.getURI(),lang);
				view.setID(viewId);
				view.setStatus(status);
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return view;
	}
	static public View getViewByViewId(int viewId) {
		View view = null;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select name,group_id,isInner,class_id,lang from view where id=?") ;
			stmt.setInt(1, viewId) ;
			ResultSet rs = stmt.executeQuery();
			if ( rs.next() ) {
				String lang = rs.getString("lang") ;
				String name = rs.getString("name");
				boolean isInner  = rs.getBoolean("isInner") ;
				String group = User.getUserNameById(rs.getInt("group_id"));
				int classID = rs.getInt("class_id");
				URIResource classURI = null;
				if(!isInner){
					classURI = URIResource.getURIResourceById(classID);
				}else{
					String classURIStr = makeInnerClassURIStr(classID) ;
					classURI = ResourceFactory.getInstance().createURIResource(classURIStr);
				}
				view = new View(name, group, isInner,classURI.getURI(),lang);
				view.setID(viewId);
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return view;
	}
	
	 public static int getViewIdByNameGroupClassID(
			String name, String group, boolean isInner,int classId) {
		int viewId = -1;
		int groupId = Group.getGroupIdByName(group);
		if ( groupId < 0 || classId < 0 ) return viewId;
		viewId = getViewIdByNameGroupClassID(name,groupId,isInner,classId);
		return viewId;
	}
	 
	 public static int getViewIdByNameGroupClassID(
				String name, int groupID, boolean isInner,int classId) {
	     int viewId = -1;
		 try {
				Connection conn = DBConnectionFactory.getConnection();
				PreparedStatement stmt = conn.prepareStatement("select id from view where name=? and group_id=? and class_id=? and isInner=?");
				stmt.setString(1, name);
				stmt.setInt(2, groupID);
				stmt.setInt(3, classId);
				stmt.setBoolean(4, isInner);
				ResultSet rs = stmt.executeQuery();
				if ( rs.next() ) {
					viewId = rs.getInt("id");
				}
				rs.close();
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return viewId;		 
	 }
	
	/**
	 * get available view of a class which directedly specified on the class
	 * @param classID
	 * @return Empty if none;
	 */
	public static  HashSet<View> getDirectViewsOfClass(boolean isInner,int classID){
		HashSet<View> result  =  new HashSet<View>();
		Connection con = DBConnectionFactory.getConnection();
		try {
			PreparedStatement ps = con.prepareStatement("select id,name,group_id,lang,use_times from view where isInner=? and class_id=?") ;
			ps.setBoolean(1, isInner) ;
			ps.setInt(2, classID) ;
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				String name = rs.getString("name") ;
				int groupID = rs.getInt("group_id");
				String lang = rs.getString("lang");
				int id  = rs.getInt("id") ;
				int use_times = rs.getInt("use_times") ;
				String classURIStr = null;
				if(!isInner)
					try {
						classURIStr = URIIDCache.getInstance().getURI(classID);
					} catch (Throwable e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				else{
					classURIStr = makeInnerClassURIStr(classID);
				}
				View view = new View(name, Group.getGroupNameById(groupID),
						isInner, classURIStr, lang);
				view.setUseTimes(use_times);
				view.setID(id);
				result.add(view);
			}
			rs.close();
			ps.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * get all available views of a class
	 * @param classID
	 * @return Empty if none;
	 */
	public static  ArrayList<View> getAvailableViewsOfClass(boolean isInner,int classID,String lang){
		ArrayList<View> result = new ArrayList<View>();

		// check if the cache table is expire. If expire ,recompute the
		// available views and wait the computation finished
		boolean expireFlag = true;
		while (expireFlag) {
			expireFlag = ViewCache.getInstance().isExpireOrUnavailable(isInner,
					classID);
			if (expireFlag) {
				// Expire ,so compute new views of the class
				// During computing, get the class's superclass's unvisited
				// views
				ViewCache.getInstance().computeAvailableViews(isInner, classID);
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		Connection con = DBConnectionFactory.getConnection();
		// get the available views which is not trashed & favored of the
		// specific page
		String views = "";
		try {
			PreparedStatement selectStmt = null;
			selectStmt = con
					.prepareStatement("select viewId from class_views,view where viewId=view.id and class_views.classId=? and class_views.lang=? and class_views.isInner=? ORDER BY view.name");
			selectStmt.setInt(1, classID);
			selectStmt.setString(2, lang);
			selectStmt.setBoolean(3, isInner);
			ResultSet rs = selectStmt.executeQuery();
			while (rs.next()) {
				int viewId = rs.getInt("viewId");
				views += viewId + ",";
				View view = View.getViewByViewId(viewId);
				view.setID(viewId);
				result.add(view);
			}
			rs.close();
			selectStmt.close();
			con.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public void setID(int id){
		this.id = id; 
	}
	
	public int getID(){
		if(this.id<=0){
			int classID =computeClassID();
			this.id = View.getViewIdByNameGroupClassID(this.name, this.group, this.isInner,classID);
			
		}
		return this.id;
	}
	
	/**
	 * rename the view and update the database
	 * @param newName
	 */
	public void rename(String newName) {
		int id = this.getID();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.prepareStatement("update view set name =?, update_time = NOW() where id=?");
			stmt.setString(1, newName);
			stmt.setInt(2, id) ;
			stmt.executeUpdate();
			stmt.close();
			conn.close();
			
			this.name = newName;
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	

	
	public static void addUseTimes(int viewID,int useTimes) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"update view " +
					"set use_times = use_times+values(use_times)" +
					" where id= %d",
					useTimes, viewID));
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * get the language of the view
	 * @param viewID. The view ID
	 * @return the language
	 */
	public static String getLanguage(int viewID) {
		String language = null;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select lang from view " +
					"where id= %d",viewID));
			if ( rs.next() ) {
				language = rs.getString("lang");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return language;
	}
	
	public String getLanguage(){
		if(this.language==null){
			int classID = computeClassID();
			language = getLanguage(getViewIdByNameGroupClassID(this.name,this.group,this.isInner,classID));
		}
		return language;
	}
	
	public void setUseTimes(int useTimes){
		this.useTimes = useTimes;
	}
	
	public int getUseTimes(){
		if(this.useTimes<0){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				Statement stmt = conn.createStatement();
				int classID = computeClassID();
				int viewID = getViewIdByNameGroupClassID(this.name,this.group,this.isInner,classID);
				ResultSet rs = stmt.executeQuery(String.format(
						"select use_times from view " +
						"where id= %d",viewID));
				if ( rs.next() ) {
					language = rs.getString("lang");
				}
				rs.close();
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return this.useTimes;
	}
	
	public String getName() {
		return name;
	}
	
	
	/**
	 * get label of the datamember in the specific view
	 * @param viewID
	 * @return
	 */
	public  static String getLabelInView(int viewID,int dmtype,int dmid) {
		// TODO Auto-generated method stub
		String label = null;
		Connection con =DBConnectionFactory.getConnection();
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery(String.format("select label from view_dm " +
					"where view_id=%d and dm_type=%d and dm_id=%d",viewID,dmtype,dmid) );
			if(rs.next()){
				label = rs.getString("label");
			}
			stmt.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return label;
	}
	
	/**
	 * get group id of the view of viewID
	 * @param viewID
	 * @return
	 */
	public static  int getGroupIDByViewID(int viewID) {
		int result = -1;
		
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select group_id from view where id=?") ;
			stmt.setInt(1, viewID) ;
			ResultSet rs = stmt.executeQuery();
			if ( rs.next() ) {
				result = rs.getInt("group_id") ;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return result;
	}
	
	public String getGroup(){
		return this.group;
	}
	
	public void setLanguage(String language) {
		this.language = language;
	}
	
	public void setClassURI(URIResource classURI) {
		this.classURI = classURI;
	}

	public URIResource getClassURI() {
		return classURI;
	}
	
	
	/**
	 * to see whether the view is on a inner class
	 * @param viewID
	 * @return
	 */
	public static boolean isInner(int viewID){
		boolean result= false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select isInner from view where id=?") ;
			stmt.setInt(1, viewID) ;
			ResultSet rs = stmt.executeQuery();
			if ( rs.next() ) {
				result = rs.getBoolean("isInner") ;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * get the class of the view identified by viewID.
	 * This function must be used with isInner()
	 * @param viewID. The view ID
	 * @return
	 */
	public static int  getClassIDByViewID(int viewID){
		int result = 0;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt =conn
			     .prepareStatement("select class_id from view where id=?") ;
			stmt.setInt(1, viewID) ;
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				result = rs.getInt("class_id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * store view reference information
	 * @param viewID. The view referred to other views
	 * @param referredToViews. The view referred by other views with the count
	 */
	public static void storeReference(int viewId,HashMap<Integer,Integer> referredToViews) {
		if(!View.isThere(viewId)) return;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"delete from view_ref where to_view_id=%d",viewId)) ;
			PreparedStatement pstmt = conn.prepareStatement(
					"insert into view_ref(from_view_id, to_view_id,times) " +
					"values(?, ?,?)");
			pstmt.setInt(2, viewId);
			for (Integer viewID : referredToViews.keySet()) {
			    int count = referredToViews.get(viewID) ;
				pstmt.setInt(1, viewID);
				pstmt.setInt(3, count) ;
				pstmt.executeUpdate();
			}
			stmt.close();
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * get the views to which view of id viewId referred to
	 * @param viewId. The view id
	 * @return the views referred to
	 */
	public static HashSet<Integer> getReferredToViews(int viewId) {
		HashSet<Integer> referredTo = new HashSet<Integer>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select from_view_id " +
					"from view_ref " +
					"where to_view_id = %d",
					viewId));
			while ( rs.next() ) {
				referredTo.add(rs.getInt("from_view_id"));
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return referredTo;
	}
	
	/**
	 * get the views which refer to view of id viewId
	 * @param viewId. The view id
	 * @return the views refer to the view of viewId
	 */
	public HashSet<Integer> getReferredByViews(int viewId) {
		HashSet<Integer> referredBy = new HashSet<Integer>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select to_view_id " +
					"from view_ref " +
					"where from_view_id = %d",
					viewId));
			while ( rs.next() ) {
				referredBy.add(rs.getInt("to_view_id"));
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return referredBy;
	}
	
	/**
	 *找到对一个viewID标识的view翻译生成的view，如果没有，则返回0
	 * 以后系统扩展了语言，那么这里应该返回arrylist数组
	 * @param viewID
	 * @return
	 */
	public static int getTranlatedView(int viewID){
		int result = 0;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select id from view where id!=%d and id!=ov_id and ov_id in (select ov_id " +
					"from view where id = %d)",viewID,viewID));
			if ( rs.next() ) {
				result = rs.getInt("id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * check whether the view is created by translation
	 * @param viewID
	 * @return
	 */
	public static boolean isTranslatedView(int viewID) {
		boolean result = true;
		
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format("select null from view where id=%d and id=ov_id",viewID));
			if(rs.next()){
				result = false;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return result;
	}	
	
	/**
	 * 得到翻译视图的起源
	 * @param viewID.翻译视图
	 * @return.翻译视图起源
	 *     返回起源视图id .如果不存在（如被删除了），那么返回0
	 */
	public static int getSrcTranlatedView(int viewID){
	    int vid = 0;
		
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format("select ov_id from view where id=%d ",viewID));
			if(rs.next()){
				vid = rs.getInt("ov_id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return vid;
	}
	
	/**
	 * get the datamembers of a view
	 * @param viewId. The view id
	 * @return empty if none
	 */
	public static  ArrayList<DataMember> getDataMembers(int viewId) {
		if(viewId<=0)
			throw new IllegalArgumentException("This function's viewId must be larger than 0");
		ArrayList<DataMember> result = new ArrayList<DataMember>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			PreparedStatement delStatement = conn.prepareStatement("delete from view_dm where view_id=? and seq=?");
			ResultSet rs = stmt.executeQuery(String.format(
					"select dm_type, dm_id,inverse,value_type,functional,seq " +
					"from view_dm " +
					"where view_id = %d " +
					"order by seq", viewId));
			while ( rs.next() ) {
				int seq = rs.getInt("seq") ;
				int dmType = rs.getInt("dm_type");
				int dmId = rs.getInt("dm_id");
				int vtype = rs.getInt("value_type") ;
				boolean funct = rs.getBoolean("functional");
				boolean inverse = rs.getBoolean("inverse") ;
				if ( dmType == DataMember.CUSTOM_DATAMEMBER ){
					CustomDataMember dm = CustomDataMember.getCustomDataMemberById(dmId) ;
					if(dm==null){
						delStatement.setInt(1, viewId);
						delStatement.setInt(2, seq) ;
						delStatement.executeUpdate();
						continue;
					}
					dm.setID(dmId) ;
					dm.setFunctional(funct);
 					result.add(dm) ;
				}
				else if ( dmType == DataMember.URI_DATAMEMBER ){
					try {
						String uri = URIIDCache.getInstance().getURI(dmId);
						if(uri==null){
							delStatement.setInt(1, viewId);
							delStatement.setInt(2, seq) ;
							delStatement.executeUpdate();
							continue;
						}
						URIDataMember dm  = new URIDataMember(uri);
						dm.setID(dmId) ;
						dm.setInverse(inverse) ;
						dm.setValueType(vtype) ;
						dm.setFunctional(funct) ;
						result.add(dm) ;
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			rs.close();
			delStatement.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * get all the custom datamember IDs referred to by this view
	 * @param viewID. view id
	 * @return all the custom datamembers
	 */
	public static HashSet<Integer> getReferedCustomDataMemberIDs(int viewID){
		HashSet<Integer> result =new HashSet<Integer>();
		HashSet<Integer> visited = new HashSet<Integer>();
	    ArrayList<Integer> todo = new ArrayList<Integer>();
		ArrayList<DataMember> dms =getDataMembers(viewID);
		for(DataMember dm:dms ){
			if(dm instanceof CustomDataMember){
				CustomDataMember cdm = (CustomDataMember)dm;
				if(!visited.contains(cdm.getID())){
					visited.add(cdm.getID()) ;
					todo.add(cdm.getID());
					result.add(cdm.getID());
				}
 			}
		}
		
		while(todo.size()>0){
			Integer mint = todo.remove(0) ;
			ArrayList<Base> bases = CustomDataMember.getBasesByDMId(mint) ;
			for(Base base:bases){
				if(base.getDMType()==DataMember.CUSTOM_DATAMEMBER){
					if(!visited.contains(base.getID())){
						visited.add(base.getID());
						todo.add(base.getID()) ;
						result.add(base.getID());
					}
				}
			}
		}
		
		return result;
	}
	
	/**
	 * 得到uriIDs的前向datamembers
	 * @param uriIDs
	 * @return
	 */
	public static HashSet<DataMember> getFowardMembers(HashSet<Integer> uriIDs ) {
		HashSet<DataMember> result = new HashSet<DataMember>();
		
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.prepareStatement("select distinct p from quadruple where doc_id=? and s=?");
			for(Integer uriID:uriIDs){
				int deref_doc = 0 ;
				try {
					deref_doc = DBOperations.getDereferenceDocID(URIIDCache.getInstance().getURI(uriID)) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				stmt.setInt(1, deref_doc) ;
				String s = "u"+uriID;
				stmt.setString(2, s) ;
				ResultSet rs = stmt.executeQuery() ;
				while(rs.next()){
					int pid= Integer.parseInt(rs.getString("p").substring(1))  ;
					String pstr = null;
					try {
						pstr = URIIDCache.getInstance().getURI(new Integer(pid));
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIDataMember dm = new URIDataMember(pstr);
					dm.setID(pid) ;
					dm.setInverse(false) ;
					result.add(dm) ;
				}
				rs.close();
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 得到uriIDs的后向datamembers
	 * @param uriIDs
	 * @return
	 */
	public static HashSet<DataMember> getBackwardMembers(HashSet<Integer> uriIDs ) {
		HashSet<DataMember> result = new HashSet<DataMember>();
		
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.prepareStatement("select distinct p from quadruple where doc_id=? and o=?");
			for(Integer uriID:uriIDs){
				int deref_doc = 0 ;
				try {
					deref_doc = DBOperations.getDereferenceDocID(URIIDCache.getInstance().getURI(uriID)) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				stmt.setInt(1, deref_doc) ;
				String o = "u"+uriID;
				stmt.setString(2, o) ;
				ResultSet rs = stmt.executeQuery() ;
				while(rs.next()){
					int pid= Integer.parseInt(rs.getString("p").substring(1))  ;
					String pstr = null;
					try {
						pstr = URIIDCache.getInstance().getURI(new Integer(pid));
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIDataMember dm = new URIDataMember(pstr);
					dm.setID(pid) ;
					dm.setInverse(true) ;
					result.add(dm) ;
				}
				rs.close();
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * serialize the view which is creatd by edition. If exists return false;
	 * @return false if exist
	 */
	public boolean serializeByEdit() {
		int groupId = Group.getGroupIdByName(this.group);
		int classId = computeClassID();
		if ( groupId < 0 || classId < 0 ) return false;
		int viewId = getViewIdByNameGroupClassID(
				name, this.group, this.isInner,classId);
		if ( viewId >=0 ) return false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement insertStmt = conn.prepareStatement("insert into view(name, group_id, isInner, class_id, lang,create_time,update_time) values(?,?,?,?,?,NOW(),NOW())");
			insertStmt.setString(1, name);
			insertStmt.setInt(2, groupId);
			insertStmt.setBoolean(3, this.isInner);
			insertStmt.setInt(4, classId);
			insertStmt.setString(5, language);
			insertStmt.executeUpdate();
		
			viewId = getViewIdByNameGroupClassID(
					name, this.group, this.isInner,classId);
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"update view " +
					"set ov_id = %d " +
					"where id= %d",viewId,viewId));
			insertStmt.close();
			stmt.close();
			conn.close();
			
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * serialize the view which is creatd by translation. If exists return false;
	 * @param sameCateViewID. The view id from which this view translated
	 * @return false if exist
	 */
	public boolean serializeByTranslate(int viewTranslatedID) {
		int groupId = Group.getGroupIdByName(this.group);
		int classId = computeClassID();
		if ( groupId < 0 || classId < 0 ) return false;
		int viewId = getViewIdByNameGroupClassID(
				name, this.group, this.isInner,classId);
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement insertStmt = conn.prepareStatement("insert ignore into view(name, group_id, isInner, class_id, lang,create_time,update_time) values(?,?,?,?,?,NOW(),NOW()");
			insertStmt.setString(1, name);
			insertStmt.setInt(2, groupId);
			insertStmt.setBoolean(3, this.isInner);
			insertStmt.setInt(4, classId);
			insertStmt.setString(5, language);
			insertStmt.executeUpdate();
			insertStmt.close();
			
			viewId = getViewIdByNameGroupClassID(
					name, this.group, this.isInner,classId);
			Statement cstmt = conn.createStatement();
			cstmt.executeUpdate(String.format(
					"update view " +
					"set ov_id = %d " +
					"where id= %d",viewTranslatedID,viewId));
			cstmt.close();
			
			conn.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * serialize the datamembers of a view, if the datamember is custom
	 *    if it is of group, then reference else copy
	 * @param viewId
	 * @param groupID
	 * @param datamembers. the origin datamebers used by user in the view
	 * @param labels. the label of datamember in this view
	 */
	public static void serializeDataMembers(int viewId,int groupID,ArrayList<DataMember> datamembers,ArrayList<String> labels){
		ArrayList<DataMember> dms = new ArrayList<DataMember>();
		for(DataMember dm:datamembers){
			if(dm instanceof URIDataMember){
				dms.add(dm) ;
			}else{
				CustomDataMember datamember = (CustomDataMember)dm;
				if(CustomDataMember.hasAuthor(groupID, datamember.getID())){
					dms.add(datamember);
				}else{
					CustomDataMember cpdm = datamember.deepCopy();
					dms.add(cpdm);
				}
			}
		}
		serializeDataMembers(viewId,dms,labels);
	}
	
	/**
	 * serialize the datamembers of a view
	 * @param viewId. The view id
	 * @param dataMembers.The memory objects of datamembers
	 */
	private static void serializeDataMembers(int viewId, ArrayList<DataMember> dataMembers,ArrayList<String> labels) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"delete from view_dm " +
					"where view_id = %d", viewId));
			stmt.close();
			PreparedStatement pstmt = conn.prepareStatement(
					"insert into view_dm" +
					"(view_id, seq, dm_type, dm_id,inverse,value_type,functional,label) " +
					"values(?, ?, ?, ?,?,?,?,?)");
			pstmt.setInt(1, viewId);
			for (int seq=0;seq<dataMembers.size();seq++) {
				int dmType = 0;
				int dmId = 0;
				boolean inverse = false;
				boolean functional = false;
				int value_type = 0;
				String label = labels.get(seq) ;
			    DataMember dm = dataMembers.get(seq);
			    if(dm instanceof URIDataMember){
			    	URIDataMember datamember = (URIDataMember)dm;
			    	String uri = datamember.getURI();
			    	try {
						dmId = URIIDCache.getInstance().getURIID(uri, true) ;
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					dmType = DataMember.URI_DATAMEMBER;
					inverse = datamember.isInverse();
					value_type = datamember.getValueType(inverse);
					functional = datamember.getFunctional();
			    }else{
			    	CustomDataMember datamember = (CustomDataMember)dm;
			    	dmType = DataMember.CUSTOM_DATAMEMBER;
			    	dmId = CustomDataMember.getDMIdByNameGroupClassIDIsCopy(datamember.getName(),datamember.getGroup(),datamember.isInner(),datamember.getClassID(),datamember.isCopy()) ;
			    	inverse = false;
			    	value_type = datamember.getValueType();
					functional = datamember.getFunctional();
			    }
				pstmt.setInt(2, seq);
				pstmt.setInt(3, dmType);
				pstmt.setInt(4, dmId);
				pstmt.setBoolean(5, inverse);
				pstmt.setInt(6, value_type);
				pstmt.setBoolean(7, functional);
				pstmt.setString(8, label);
				pstmt.executeUpdate();
			}
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((classURI == null) ? 0 : classURI.hashCode());
		result = prime * result + ((group == null) ? 0 : group.hashCode());
		result = prime * result + (isInner ? 1231 : 1237);
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		View other = (View) obj;
		if (classURI == null) {
			if (other.classURI != null)
				return false;
		} else if (!classURI.equals(other.classURI))
			return false;
		if (group == null) {
			if (other.group != null)
				return false;
		} else if (!group.equals(other.group))
			return false;
		if (isInner != other.isInner)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	/**
	 * remove trash views for user
	 * @param viewID
	 * @param user
	 */
	public static void removeTrashViewsForUser(
			int viewID, String user,boolean isInner,int classID) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("delete from view_trash where view_id=? and user_id=? and isInner=? and class_id=?");
			stmt.setInt(1, viewID);
			stmt.setInt(2, User.getUserIdByName(user));
			stmt.setBoolean(3, isInner);
			stmt.setInt(4, classID);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * add favor view for user
	 * @param viewID
	 * @param user
	 * @param classID
	 * @param lang
	 * @param isInner
	 */
	public static void addFavorViewsForClassLangUser(
			int viewID, String user,int classID, String lang,boolean isInner) {
		if(!View.isThere(viewID)) return;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.
			   prepareStatement("insert ignore into view_favor(user_id,view_id,class_id,lang,isInner) values(?,?,?,?,?)");
		    stmt.setInt(1, User.getUserIdByName(user)) ;
		    stmt.setInt(2, viewID);
		    stmt.setInt(3, classID) ;
		    stmt.setString(4, lang) ;
		    stmt.setBoolean(5, isInner) ;
		    stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * add trashview for user
	 * @param viewID
	 * @param user
	 * @param classID
	 * @param lang
	 * @param isInner
	 */
	public static void addTrashViewsForClassLangUser(
			int viewID, String user,int classID, String lang,boolean isInner) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.
			   prepareStatement("insert into view_trash(user_id,view_id,class_id,lang,isInner) values(?,?,?,?,?)");
		    stmt.setInt(1, User.getUserIdByName(user)) ;
		    stmt.setInt(2, viewID);
		    stmt.setInt(3, classID) ;
		    stmt.setString(4, lang) ;
		    stmt.setBoolean(5, isInner) ;
		    stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * remove favor views for user
	 * @param viewID
	 * @param user
	 */
	public static void removeFavorViewsForUser(
			int viewID, String user,boolean isInner,int classID) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("delete from view_favor where view_id=? and user_id=? and isInner=? and class_id=?");
			stmt.setInt(1, viewID);
			stmt.setInt(2, User.getUserIdByName(user));
			stmt.setBoolean(3, isInner);
			stmt.setInt(4, classID);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * serialize view layout for user
	 * @param viewID. the view id to be serialized
	 * @param user.username
	 * @param layout.layout
	 */
	public static void serializeLayoutForUser(int viewID,String user, int layout) {
		new User(user).serializeViewLayout(viewID, layout);
	}
	
	/**
	 * get view layout for user
	 * @param viewID. the view id to be serialized
	 * @param user.username
	 * @param layout.layout
	 * return -1 if none
	 */
	public static int  getLayoutForUser(int viewID,String user){
		int layout = new User(user).getViewLayout(viewID) ;
		return layout;
	}
	
	/**
	 * get the pop views. For a specific user, remove the views he hated. 
	 * Use the cache to store which views a class has
	 * @param isInner. if the class is inner class
	 * @param classID. the minimal class id an entity belongs to
	 * @param lang. the display language
	 * @param user. the user which may be null
	 * @param start. the paging start parameter
	 * @param length. total results in the page
	 * return. ordered list of views in current page. Empty if none.
	 */
	public static ArrayList<View> getPopViews(boolean isInner,int classID, String lang, String user, int start, int length){
		LinkedList<View> result1 = new LinkedList<View>();
		ArrayList<View> result = new ArrayList<View>();
			int userID = User.getUserIdByName(user);

			// check if the cache table is expire. If expire ,recompute the
			// available views and wait the computation finished
			boolean expireFlag = true;
			while (expireFlag) {
				expireFlag = ViewCache.getInstance().isExpireOrUnavailable(isInner, classID);
				if (expireFlag) {
					// Expire ,so compute new views of the class
					// During computing, get the class's superclass's unvisited
					// views
					ViewCache.getInstance().computeAvailableViews(isInner, classID);
				}
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			Connection con = DBConnectionFactory.getConnection();
			//get the available views which is not trashed & favored of the specific page 
			String views = "";
			try{
				PreparedStatement selectStmt  = null;
				if(user==null){
				   if(length>0){
					   selectStmt = con.
					   	prepareStatement("select viewId from class_views where classId=? and lang=? and isInner=? ORDER BY use_times DESC LIMIT ?,?;"); 
				   }else{
					   selectStmt = con.
					   	prepareStatement("select viewId from class_views where classId=? and lang=? and isInner=? ORDER BY use_times DESC"); 
				   }
				   selectStmt.setInt(1, classID) ;
				   selectStmt.setString(2, lang) ;
				   selectStmt.setBoolean(3, isInner) ;
				   if(length>0){
					   selectStmt.setInt(4, start);
					   selectStmt.setInt(5, start + length);
				   }
				}else{
					//order by use_times and not in favor and trashed views
					if(length>0){
						selectStmt = con.
							prepareStatement("select viewId from class_views where isInner=? and classId=? and lang=? and " +
							"not exists( select view_id from view_trash where isInner = class_views.isInner and view_id = class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) and " +
							"not exists( select view_id from view_favor where isInner = class_views.isInner and view_id=class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) ORDER BY use_times DESC LIMIT ?,?;") ;
					}else{
						selectStmt = con.
						prepareStatement("select viewId from class_views where isInner=? and classId=? and lang=? and " +
						"not exists( select view_id from view_trash where isInner = class_views.isInner and view_id = class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) and " +
						"not exists( select view_id from view_favor where isInner = class_views.isInner and view_id=class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) ORDER BY use_times DESC") ;
					}
					selectStmt.setBoolean(1,isInner);
					selectStmt.setInt(2,classID);
					selectStmt.setString(3, lang) ;
					selectStmt.setInt(4, userID);
					selectStmt.setInt(5, userID) ;
					if(length>0){
						selectStmt.setInt(6, start);
						selectStmt.setInt(7, start + length);
					}
				}
				ResultSet rs = selectStmt.executeQuery();
				while(rs.next()){
					int viewId = rs.getInt("viewId") ;
					views += viewId + ",";	
					View view = View.getViewByViewId(viewId);
					view.setID(viewId) ;
					result1.add(view);
				}
				if(views.length() > 0){

					views = views.substring(0, views.length() - 1);
					views = " (user_day_view_visit.view_id in (" + views + ")) AND ";
				}
				else{
					return new ArrayList<View>(result1);
				}
				rs.close();
				selectStmt.close();
				
				PreparedStatement sort_ps = con.prepareStatement("SELECT user_day_view_visit.view_id FROM user_day_view_visit, view WHERE " +
						views + " view.lang = ? AND user_day_view_visit.view_id = view.id " +
						"GROUP BY user_day_view_visit.view_id ORDER BY sum(times_recent) ASC;");
				sort_ps.setString(1, lang);
				ResultSet sort_rs = sort_ps.executeQuery();
				
				while(sort_rs.next()){
					int viewId = sort_rs.getInt("user_day_view_visit.view_id");
					View view = View.getViewByViewId(viewId);
					view.setID(viewId);
					result.add(view);   
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			Iterator<View> iter = result.iterator();
			while(iter.hasNext()){
				View v = iter.next();
				result1.remove(v);
				result1.addFirst(v);
			}
			return new ArrayList<View>(result1);
	}
	
	public static int getPopViewNum(boolean isInner,int classID, String lang, String user){
        int result = 0;
		int userID = User.getUserIdByName(user) ;
		//check if the cache table is expire. If expire ,recompute the available views and wait the computation finished
		boolean expireFlag = true;
		while(expireFlag) {
			expireFlag = ViewCache.getInstance().isExpireOrUnavailable(isInner,classID) ;
			if(expireFlag){
				//Expire ,so compute new views of the class
				//During computing, get the class's superclass's unvisited views
	            ViewCache.getInstance().computeAvailableViews(isInner,classID) ;
			}
            try {
				Thread.sleep(10) ;
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		Connection con = DBConnectionFactory.getConnection();
		//get the available views which is not trashed & favored of the specific page 
		try{
			PreparedStatement selectStmt  = null;
			if(user==null){
			   selectStmt = con.
			     prepareStatement("select count(viewId) as num from class_views where classId=? and lang=? and isInner=? order by use_times "); 
			   selectStmt.setInt(1, classID) ;
			   selectStmt.setString(2, lang) ;
			   selectStmt.setBoolean(3,isInner) ;
			}else{
				//order by use_times and not in favor and trashed views
				selectStmt = con.
				prepareStatement("select count(viewId) as num from class_views where isInner=? and classId=? and lang=? and " +
						"not exists( select view_id from view_trash where isInner = class_views.isInner and view_id = class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) and " +
						"not exists( select view_id from view_favor where isInner = class_views.isInner and view_id=class_views.viewId and user_id=? and class_id=class_views.classId and lang=class_views.lang) " +
						"order by use_times ") ;
				selectStmt.setBoolean(1,isInner);
				selectStmt.setInt(2,classID);
				selectStmt.setString(3, lang) ;
				selectStmt.setInt(4, userID);
				selectStmt.setInt(5, userID) ;
			}
			ResultSet rs = selectStmt.executeQuery();
			while(rs.next()){
				result = rs.getInt("num");
			}
			rs.close();
			selectStmt.close();
		}catch(SQLException e){
			e.printStackTrace();
		}
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;		
	}
	
	/**
	 * get the favor views of a specific user. Favor on a class has no impact on its superclass or subclass.
	 * Use the cache to store which views a class has
	 * @classID. the class an entity belongs to
	 * @lang. the display language
	 * @user. the user 
	 * @start. the paging start parameter
	 * @length. total results in the page
	 * return. ordered list of views in current page. Empty if none.
	 */	
	public static ArrayList<View> getFavorViews(boolean isInner,int classID, String lang, String user, int start, int length){
		ArrayList<View> result = new ArrayList<View>();
		if(user==null){
			throw new IllegalArgumentException("User can not be null");
		}
		int userID  = User.getUserIdByName(user) ;
		Connection con = DBConnectionFactory.getConnection();
		try {
			//order by name and paging
			PreparedStatement ps = null;
			if(length>0){
				ps = con.prepareStatement("select view_id from view_favor,view  where " +
					"id=view_id and view_favor.user_id=? and view_favor.class_id=? and view_favor.lang=? and view_favor.isInner=? order by name limit ?,?") ;
			}else{
				ps = con.prepareStatement("select view_id from view_favor,view  where " +
				"id=view_id and view_favor.user_id=? and view_favor.class_id=? and view_favor.lang=? and view_favor.isInner=? order by name") ;
			}
			ps.setInt(1,userID);
			ps.setInt(2, classID);
			ps.setString(3, lang) ;
			ps.setBoolean(4, isInner) ;
			if(length>0){
				ps.setInt(5, start) ;
				ps.setInt(6, length) ;
			}
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				int viewID = rs.getInt("view_id") ;
				View view  =  View.getViewByViewId(viewID) ;
				view.setStatus(STATUS_FAVOR);
				result.add(view) ;
			}
			rs.close();
			ps.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	
	
	public static int  getFavorViewsNum(boolean isInner,int classID, String lang, String user){
	    int result = 0;
		if(user==null){
			throw new IllegalArgumentException("User can not be null");
		}
		int userID  = User.getUserIdByName(user) ;
		Connection con = DBConnectionFactory.getConnection();
		try {
			//order by name and paging
			PreparedStatement ps = con.prepareStatement("select count(view_id) as num from view_favor,view  where " +
					"id=view_id and view_favor.user_id=? and view_favor.class_id=? and view_favor.lang=? and view_favor.isInner=? order by name ") ;
			ps.setInt(1,userID);
			ps.setInt(2, classID);
			ps.setString(3, lang) ;
			ps.setBoolean(4, isInner) ;
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				result = rs.getInt("num") ;
			}
			rs.close();
			ps.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;		
	}
	
	/**
	 * get the trashed views of a specific user.Trash on a class has no impact on its superclass or subclass.
	 * Use the cache to store which views a class has
	 * @classID. the class an entity belongs to
	 * @lang. the display language
	 * @user. the user now
	 * @start. the paging start parameter
	 * @length. total results in the page
	 * return. ordered list of views in current page.
	 */	
	public static ArrayList<View> getTrashedViews(boolean isInner,int classID, String lang, String user, int start, int length){
		ArrayList<View> result = new ArrayList<View>();
		if(user==null){
			throw new IllegalArgumentException("User can not be null");
		}
		int userID  = User.getUserIdByName(user) ;
		Connection con = DBConnectionFactory.getConnection();
		try {
			//order by name and paging
			PreparedStatement ps = null;
			if(length>0){
				ps= con.prepareStatement("select view_id from view_trash,view  where " +
					"id=view_id and view_trash.user_id=? and view_trash.class_id=? and view_trash.lang=? and view_trash.isInner=? order by name limit ?,?") ;
			}else{
				ps = con.prepareStatement("select view_id from view_trash,view  where " +
				"id=view_id and view_trash.user_id=? and view_trash.class_id=? and view_trash.lang=? and view_trash.isInner=? order by name") ;
			}
			ps.setInt(1,userID);
			ps.setInt(2, classID);
			ps.setString(3, lang) ;
			ps.setBoolean(4, isInner) ;
			if(length>0){
				ps.setInt(5, start) ;
				ps.setInt(6, length) ;
			}
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				int viewID = rs.getInt("view_id") ;
				View view  =  View.getViewByViewId(viewID) ;
				view.setStatus(STATUS_TRASH);
				result.add(view) ;
			}
			rs.close();
			ps.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static int getTrashedViewsNum(boolean isInner,int classID, String lang, String user){
        int result = 0;
		if(user==null){
			throw new IllegalArgumentException("User can not be null");
		}
		int userID  = User.getUserIdByName(user) ;
		Connection con = DBConnectionFactory.getConnection();
		try {
			//order by name and paging
			PreparedStatement ps = con.prepareStatement("select count(view_id) as num from view_trash,view  where " +
					"id=view_id and view_trash.user_id=? and view_trash.class_id=? and view_trash.lang=? and view_trash.isInner=? order by name") ;
			ps.setInt(1,userID);
			ps.setInt(2, classID);
			ps.setString(3, lang) ;
			ps.setBoolean(4, isInner) ;
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				result = rs.getInt("num");
			}
			rs.close();
			ps.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	/*删除view*/
	public static void delete(int viewID){
		Connection conn = DBConnectionFactory.getConnection();
		try {
			Statement stmt = conn.createStatement();
			//删除 class_views中缓存的信息
			stmt.executeUpdate(String.format("delete from class_views where viewId=%d", viewID));
			//删除 user_view中信息
			stmt.executeUpdate(String.format("delete from user_view where view_id=%d", viewID));
			//delete info of user_view_visit_control
			stmt.executeUpdate(String.format("delete from user_day_visit_control where member_type=0 and member_id=%d and control_type='%s'", viewID,Management.CONTROL_VIEW_TYPE));
			//delete info of view_ref
			stmt.executeUpdate(String.format("delete from view_ref where from_view_id=%d", viewID));
			stmt.executeUpdate(String.format("delete from view_ref where to_view_id=%d", viewID));
			//delete info of view_trash
			stmt.executeUpdate(String.format("delete from view_trash where view_id=%d", viewID));
			//delete info of view_favor
			stmt.executeUpdate(String.format("delete from view_favor where view_id=%d", viewID));
			//delete info of view_dm
			stmt.executeUpdate(String.format("delete from view_dm where view_id=%d", viewID));
			//如果它是其它翻译view的起源，那么修改其它翻译view使它们变成普通的视图
			if(!View.isTranslatedView(viewID)){
				int transViewID = View.getTranlatedView(viewID);
				if(transViewID>0){
					stmt.executeUpdate(String.format("update view set ov_id=%d where id=%d",transViewID,transViewID));
				}
				
			}
			//delete info of view
			stmt.executeUpdate(String.format("delete from view where id=%d", viewID));
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
